<template>
  <div class="r-container">
    <input type="file" ref="upload" accept=".json" @change="executorpListchange" id="r_file_executor"
      style="display: none;">
    <div style="display:flex">
      <div class='r-opreation' style="flex:1">
        <el-tag>总数：{{ tableData.length }}</el-tag>
        <el-button style="margin-left:40px" type="primary" @click="uploadJson" round title="初始化文件">
          <el-icon style="margin-right: 4px;">
            <Document />
          </el-icon>
          初始化文件
        </el-button>
        <el-button type="primary" @click="downloadFile" round title="下载文件">
          <el-icon style="margin-right: 4px;">
            <DocumentChecked />
          </el-icon>
          下载文件
        </el-button>
        <el-button type="primary" @click="showJson" round title="查看json">
          <el-icon style="margin-right: 4px;">
            <DocumentCopy />
          </el-icon>
          查看json
        </el-button>

        <el-button v-show="!onSerachR" icon="Search" circle @click="onSerachR = true"></el-button>

        <el-button v-show="onSerachR" class="search">
          <el-icon>
            <Search />
          </el-icon>
          <input v-model="searchR" placeholder="请输入角色名称">
          <el-icon @click="onSerachR = false; searchR = ''">
            <Close />
          </el-icon>
        </el-button>
      </div>
      <div class='r-opreation' style="min-width: 360px;width: calc(30% - 20px);margin-left: 20px;">
        <el-tag style="margin-right: 20px;">选中{{ rpNum }}</el-tag>
        <el-tag v-if="rpNull" type="danger">未上传rolemenu.json</el-tag>
        <el-tag v-if="!rpNull" type="danger">{{ fileName }}</el-tag>
      </div>
    </div>
    <div class="edit" ref="edit">
      <el-table :default-sort="{ prop: 'id', order: 'ascending' }" highlight-current-row height='100%'
        empty-text='数据为空，请上传role.json'
        :data="rTableData.filter(data => !searchR || data.name.toLowerCase().includes(searchR.toLowerCase()) || data.sign.toLowerCase().includes(searchR.toLowerCase()))"
        ref="rMultipleTable" tooltip-effect="dark" style="width: 45%;">

        <el-table-column prop="sign" label="sign" show-overflow-tooltip width="80">
        </el-table-column>
        <el-table-column prop="name" label="name" show-overflow-tooltip>
        </el-table-column>
        <el-table-column prop="id" label="id">
        </el-table-column>
        <el-table-column label="操作" width="100">
          <template #default="scope">
            <el-button @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
          </template>
        </el-table-column>
      </el-table>
      <div style="height: 100%;width: 2px;background-color: #eee;margin-left: 30px;"></div>
      <div style="min-width: 360px;width: calc(30% - 20px);margin-left: 20px;height: 100%;padding-right: 10px;">
        <div style="font-size: 14px;font-weight: bold;color: #999;margin: 7px 0;">角色菜单</div>
        <el-tree ref="menuTree" v-loading="loading" :data="menuTreeData" :props="defaultProps" show-checkbox
          node-key="id" @check="handleCheckChange" height='100%' default-expand-all style="height: 100%;overflow: auto;">
          <template #default="{ node, data }">
            <span class="custom-tree-node">
              <span>{{ node.label }}</span>
              <el-button :type="data.status === 1 ? 'success' : 'info'" size="small" style="margin-left: 8px;"
                @click.stop="toggleStatus(data)">
                {{ data.status === 1 ? '启用' : '禁用' }}
              </el-button>
            </span>
          </template>
        </el-tree>
      </div>

    </div>
    <el-dialog title="json" v-model="jsonDialogShow" width="600px" center>
      <textarea class="json-txt" :value='jsonInfo'>
  </textarea>
    </el-dialog>
  </div>
</template>

<script>
import store from "../store"
import { ElMessage, ElLoading } from 'element-plus'
import { Search, Close, Document, DocumentChecked, DocumentCopy } from '@element-plus/icons-vue'

export default {
  name: "RoleMenuManager",
  components: {
    Search,
    Close,
    Document,
    DocumentChecked,
    DocumentCopy
  },
  data() {
    return {
      jsonInfo: '',
      jsonDialogShow: false,
      fileName: 'rolemenu.json',
      deleteDialogVisible: true,
      tableData: [],
      rTableData: [],
      pTableData: [],
      rpTableData: [],//选中项
      pTableDataMap: new Map(),
      roleIdMap: new Map(),
      editType: 'add',
      form: {
        name: '',
        sign: '',
        id: '',
        index: -1
      },
      multipleSelection: [],
      searchR: '',
      onSerachR: false,
      editRoleId: 0,//当前编辑的id
      editRoleIndex: 0,//当前编辑的角色索引
      editRow: {},//当前编辑的角色索引
      rpNum: 0,
      rpNull: false,
      loading: false,
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      menuTreeData: [] // 树形菜单数据
    }
  },
  store,
  methods: {
    // 处理树形菜单的勾选变化
    handleCheckChange(checkedKeys, checkInfo) {
      // 清除旧的选中状态
      if (this.tableData[this.roleIdMap.get(this.editRoleId)]) {
        this.tableData[this.roleIdMap.get(this.editRoleId)].menu = []
      } else {
        this.tableData.push({
          roleId: this.editRoleId + "",
          menu: []
        })
        this.roleIdMap.set(this.editRoleId, this.tableData.length - 1)
      }

      // 添加新的选中项
      const roleIndex = this.roleIdMap.get(this.editRoleId)
      if (roleIndex !== undefined) {
        // 调试信息 - 可以在控制台查看参数结构
        console.log('checkedKeys:', checkedKeys)
        console.log('checkInfo:', checkInfo)

        // 优先使用checkInfo中的checkedKeys数组
        let keysToProcess = []

        // 检查checkInfo中是否有checkedKeys属性（Element Plus标准格式）
        if (checkInfo && Array.isArray(checkInfo.checkedKeys)) {
          keysToProcess = checkInfo.checkedKeys
          console.log('使用checkInfo.checkedKeys:', keysToProcess)
        }
        // 检查checkedKeys本身是否为数组
        else if (Array.isArray(checkedKeys)) {
          keysToProcess = checkedKeys
          console.log('使用checkedKeys参数:', keysToProcess)
        }
        // 处理checkedKeys是单个对象的情况
        else if (checkedKeys && typeof checkedKeys === 'object' && checkedKeys.id) {
          keysToProcess = [checkedKeys.id]
          console.log('使用单个对象的id:', keysToProcess)
        }

        // 使用菜单ID数组，从pTableData中查找对应的菜单信息
        if (keysToProcess.length > 0 && this.pTableData && this.pTableData.length > 0) {
          console.log('开始根据ID查找菜单信息')

          // 创建一个菜单ID到菜单信息的映射，提高查找效率
          const menuMap = {}
          this.pTableData.forEach(menu => {
            menuMap[menu.id] = menu
          })

          // 遍历所有选中的菜单ID
          keysToProcess.forEach(key => {
            // 确保key是字符串格式
            const menuId = typeof key === 'string' ? key : String(key)

            if (menuMap[menuId]) {
              // 找到对应的菜单信息，添加到角色的menu数组中
              this.tableData[roleIndex].menu.push({
                name: menuMap[menuId].name,
                status: menuMap[menuId].status || 1,
                id: menuMap[menuId].id
              })
              console.log('添加菜单:', menuMap[menuId])
            } else {
              // 如果在menuMap中找不到，尝试在pTableData中直接查找
              const foundMenu = this.pTableData.find(menu => menu.id === menuId)
              if (foundMenu) {
                this.tableData[roleIndex].menu.push({
                  name: foundMenu.name,
                  status: foundMenu.status || 1,
                  id: foundMenu.id
                })
                console.log('通过pTableData查找并添加菜单:', foundMenu)
              } else {
                console.log('未找到菜单ID:', menuId)
              }
            }
          })
        } else {
          console.log('没有可处理的菜单ID或pTableData为空')
        }

        this.rpNum = this.tableData[roleIndex].menu.length
        console.log('最终添加的菜单数量:', this.rpNum)
        this.save()
      }
    },

    // 递归构建树形数据
    buildMenuTree(menuList) {
      const menuMap = {}
      const roots = []

      // 首先创建所有节点的映射
      menuList.forEach(menu => {
        menuMap[menu.id] = {
          ...menu,
          children: []
        }
      })

      // 构建树形结构
      menuList.forEach(menu => {
        if (menu.parentId) {
          // 如果有父节点，则添加到父节点的children中
          if (menuMap[menu.parentId]) {
            menuMap[menu.parentId].children.push(menuMap[menu.id])
          }
        } else {
          // 如果没有父节点，则是根节点
          roots.push(menuMap[menu.id])
        }
      })

      // 如果没有形成有效的树形结构，直接返回所有节点
      if (roots.length === 0) {
        return menuList.map(menu => ({
          ...menu,
          children: []
        }))
      }

      return roots
    },
    resetForm() {
      this.form = {
        name: '',
        sign: '',
        id: '',
        index: -1
      }
    },
    removeSelect() {
      let selection = this.selectedRows;
      // 确保selection是数组且不为空
      if (!Array.isArray(selection) || selection.length === 0) {
        ElMessage.warning('没有选中的项');
        return;
      }

      // 按index排序
      selection.sort(function (a, b) {
        return a.index - b.index;
      });

      // 从后往前删除，避免索引错乱
      for (let i = selection.length - 1; i >= 0; i--) {
        if (selection[i] && typeof selection[i].index === 'number') {
          this.tableData.splice(selection[i].index, 1);
        }
      }

      this.save();
      ElMessage({
        message: '已删除',
        type: 'success'
      });
    },
    downloadFile() {
      if (!this.tableData) {
        ElMessage.error('未初始化');
        return
      }
      const loading = ElLoading.service({
        lock: true,
        text: '正在整理导出...',
        background: 'rgba(0, 0, 0, 0.7)'
      });

      function fakeClick(obj) {
        var ev = document.createEvent("MouseEvents");
        ev.initMouseEvent(
          "click",
          true,
          false,
          window,
          0,
          0,
          0,
          0,
          0,
          false,
          false,
          false,
          false,
          0,
          null
        );
        obj.dispatchEvent(ev);
      }

      function exportRaw(name, data) {
        var urlObject = window.URL || window.webkitURL || window;
        var export_blob = new Blob([data]);
        var save_link = document.createElementNS(
          "http://www.w3.org/1999/xhtml",
          "a"
        );
        save_link.href = urlObject.createObjectURL(export_blob);
        save_link.download = name;
        fakeClick(save_link);
        setTimeout(() => {
          loading.close();
        }, 500);
      }
      let outJson = JSON.parse(JSON.stringify(this.tableData))
      outJson.sort(function (a, b) {
        return parseInt(a.roleId.replace('role', '')) - parseInt(b.roleId.replace('role', ''));
      })
      //整理数据
      for (let i = 0; i < outJson.length; i++) {
        outJson[i].menu.sort(function (a, b) {
          return parseInt(a.id.replace('menu', '')) - parseInt(b.id.replace('menu', ''));
        })
      }
      exportRaw(
        this.fileName,
        JSON.stringify(outJson, null, 4)
      );
    },
    cancelEdit() {
      this.editType = 'add'
      this.form = {
        name: '',
        sign: '',
        id: '',
        index: -1
      }
    },
    save() {
      sessionStorage.setItem('rmList', JSON.stringify(this.tableData))
      sessionStorage.setItem('rmFileName', this.fileName)
    },
    uploadJson() {
      var inputObj = document.querySelector(
        "#r_file_executor"
      );
      inputObj.click();
    },
    executorpListchange() {
      var files = document.querySelector("#r_file_executor").files
      let file = files[0]
      if (file.name.indexOf(".json") != file.name.length - 5) {
        ElMessage.error('不支持的文件格式');
        return;
      }

      var reader = new FileReader(); //新建一个FileReader
      reader.readAsText(file, "UTF-8"); //读取文件
      reader.onload = (evt) => {
        let roles = JSON.parse(evt.target.result)
        if (roles instanceof Array) {
          if (roles.length == 0 || roles[0].roleId === undefined) {
            ElMessage.error('格式有误');
            return
          }
          this.tableData = roles
          for (let i = 0; i < roles.length; i++) {
            this.roleIdMap.set(roles[i].roleId, i)
          }
        } else {
          ElMessage.error('格式有误');
        }
        this.fileName = file.name
        this.save();
        document.querySelector("#r_file_executor").value = ''

        this.handleEdit(0, this.rTableData[0])
        this.rpNull = false
        this.fileName = file.name
      }
    },
    handleEdit(index, row) {
      if (!row || !row.id) {
        return
      }

      // 确保表格引用存在
      if (this.$refs.rMultipleTable) {
        this.$refs.rMultipleTable.setCurrentRow(row);
      }

      this.editRoleId = row.id
      this.editRoleIndex = index
      this.editRow = row

      // 确保树引用存在
      if (this.$refs.menuTree) {
        this.$refs.menuTree.setCheckedKeys([]);
      }

      let rpTableData = []
      const roleIndex = this.roleIdMap.get(row.id);

      if (roleIndex !== undefined && this.tableData[roleIndex] && this.tableData[roleIndex].menu) {
        rpTableData = this.tableData[roleIndex].menu
        this.rpNum = rpTableData.length
      } else {
        this.rpNum = 0
      }

      this.rpTableData.splice(0, this.rpTableData.length)

      setTimeout(() => {
        // 确保树引用存在
        if (this.$refs.menuTree) {
          // 提取所有菜单ID作为选中键
          const checkedKeys = rpTableData.map(menu => menu.id)
          this.$refs.menuTree.setCheckedKeys(checkedKeys)
        }
      }, 50);
    },
    handleDelete(index) {
      this.deleteDialogVisible = false
      this.tableData.splice(index, 1)
      this.save()
    },
    showJson() {
      if (!this.tableData) {
        ElMessage.error('未初始化');
        return
      }
      const loading = ElLoading.service({
        lock: true,
        text: '正在整理导出...',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      let outJson = JSON.parse(JSON.stringify(this.tableData))
      outJson.sort(function (a, b) {
        return parseInt(a.roleId.replace('role', '')) - parseInt(b.roleId.replace('role', ''));
      })
      //整理数据
      for (let i = 0; i < outJson.length; i++) {
        outJson[i].menu.sort(function (a, b) {
          return parseInt(a.id.replace('menu', '')) - parseInt(b.id.replace('menu', ''));
        })
      }
      loading.close()

      this.jsonInfo = JSON.stringify(outJson, null, 4)
      this.jsonDialogShow = true
    },
    // 新增方法：加载初始数据
    loadInitialData() {
      try {
        // 模拟从rolemenu.json加载数据
        // 在实际应用中，这里应该使用import或fetch等方法加载文件
        // 由于直接import可能有问题，这里我们创建一些模拟数据，包含父子关系
        const mockData = [
        ];

        this.tableData = mockData;
        for (let i = 0; i < mockData.length; i++) {
          this.roleIdMap.set(mockData[i].roleId, i)
        }
        this.fileName = 'rolemenu.json';
      } catch (error) {
        console.error('加载初始数据失败:', error);
        this.rpNull = true;
      }
    },

    // 新增方法：从tableData中提取角色列表
    extractRoleListFromTableData() {
      const roleSet = new Set();
      this.rTableData = [];

      for (let i = 0; i < this.tableData.length; i++) {
        const roleId = this.tableData[i].roleId;
        if (!roleSet.has(roleId)) {
          roleSet.add(roleId);
          // 提取数字部分作为ID
          const idNum = roleId.replace('role', '');
          this.rTableData.push({
            id: roleId,
            name: `角色${idNum}`,
            sign: roleId
          });
        }
      }
    },

    // 新增方法：从tableData中提取菜单列表
    extractMenuListFromTableData() {
      const menuSet = new Set();
      this.pTableData = [];

      for (let i = 0; i < this.tableData.length; i++) {
        const menus = this.tableData[i].menu || [];
        for (let j = 0; j < menus.length; j++) {
          const menuId = menus[j].id;
          if (!menuSet.has(menuId)) {
            menuSet.add(menuId);
            // 尝试提取父子关系（这里使用简单的规则：menu000001是menu000002的父节点，以此类推）
            const menuNum = parseInt(menuId.replace('menu', ''));
            let parentId = null;

            // 简单的父子关系规则：如果菜单编号大于1且为偶数，则有父节点
            if (menuNum > 1 && menuNum % 2 === 0) {
              parentId = `menu${String(menuNum - 1).padStart(6, '0')}`;
            }

            this.pTableData.push({
              id: menuId,
              name: menus[j].name,
              status: menus[j].status || 1,
              parentId: parentId
            });
          }
        }
      }

      // 构建树形数据
      this.menuTreeData = this.buildMenuTree(this.pTableData);
    },

    // 切换菜单状态
    toggleStatus(data) {
      // 切换状态：1 -> 0 或 0 -> 1
      data.status = data.status === 1 ? 0 : 1;

      // 更新pTableData中对应菜单的状态
      const menuIndex = this.pTableDataMap.get(data.id);
      if (menuIndex !== undefined) {
        this.pTableData[menuIndex].status = data.status;
      }

      // 更新当前编辑角色下的对应菜单状态
      const roleIndex = this.roleIdMap.get(this.editRoleId);
      if (roleIndex !== undefined && this.tableData[roleIndex] && this.tableData[roleIndex].menu) {
        const menuInRole = this.tableData[roleIndex].menu.find(menu => menu.id === data.id);
        if (menuInRole) {
          menuInRole.status = data.status;
        }
      }

      // 保存数据
      this.save();

      // 保存到sessionStorage
      sessionStorage.setItem('mList', JSON.stringify(this.pTableData));
    }
  },
  computed: {

  },
  mounted() {
    this.pTableDataMap.clear()
    this.tableData.splice(0, this.tableData.length)
    this.rTableData.splice(0, this.rTableData.length)
    this.pTableData.splice(0, this.pTableData.length)

    // 优先从sessionStorage加载数据
    if (sessionStorage.getItem('rmList')) {
      this.tableData = JSON.parse(sessionStorage.getItem('rmList'))
      this.fileName = sessionStorage.getItem('rmFileName')
      for (let i = 0; i < this.tableData.length; i++) {
        this.roleIdMap.set(this.tableData[i].roleId, i)
      }
    } else {
      // 直接从rolemenu.json加载初始数据
      this.loadInitialData()
    }

    if (sessionStorage.getItem('rList')) {
      this.rTableData = JSON.parse(sessionStorage.getItem('rList'))
    } else {
      // 从tableData中提取角色列表
      this.extractRoleListFromTableData()
    }

    if (sessionStorage.getItem('mList')) {
      this.pTableData = JSON.parse(sessionStorage.getItem('mList'))
      // 构建树形数据
      this.menuTreeData = this.buildMenuTree(this.pTableData)
    } else {
      // 从tableData中提取菜单列表
      this.extractMenuListFromTableData()
    }

    // 为菜单列表创建映射
    for (let i = 0; i < this.pTableData.length; i++) {
      this.pTableDataMap.set(this.pTableData[i].id, i)
    }

    // 初始化选中第一个角色
    setTimeout(() => {
      if (this.rTableData && this.rTableData.length > 0) {
        this.handleEdit(0, this.rTableData[0])
      }
    }, 50);
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
/deep/ .el-tree-node__children {
  margin-bottom: 6px;
}

/deep/ .el-tree-node__content {
  padding: 6px 0;
}

.r-container {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
}

.json-txt {
  resize: none;
  width: 100%;
  height: 600px;
  border: none;
  outline: none;
}

.json-txt:hover {
  border: none;
  outline: none;
}

.custom-tree-node {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.r-container .r-opreation {
  text-align: left;
  margin-bottom: 10px;
}

.r-container .r-opreation .search {
  margin-left: 10px;
  display: inline-flex;
  align-items: center;
  padding: 0 14px;
  border-radius: 40px;
}

.r-container .r-opreation .search input {
  border: none;
  outline: none;
  background-color: transparent;
  margin-left: 4px;
}

.r-container .r-opreation .search i {
  color: rgba(143, 143, 143, 0.933);
}

.r-container .r-opreation .search .el-icon-close {
  cursor: pointer;
}

.r-container .r-opreation .search:hover {
  border: 1px #bcdeff solid;
}

.r-container .edit {
  display: flex;
  height: calc(100vh - 120px);
  /* 使用calc确保有足够的高度 */
  flex: 1;
}

.r-container .edit .el-table {
  flex: 1;
}

.r-container .edit .el-form {
  width: 300px;
  margin-left: 40px;
}
</style>